package cn.com.jcoo.security;


import cn.com.jcoo.StringUtils;

/**
 * <li>数据脱敏工具类</li>
 *
 * @author jcoo
 * @version 1.0
 * @since 2021/11/6
 */
public class DesensitizeUtils {

	/**
	 * 根据指定长度进行数据脱敏
	 *
	 * @param value 值
	 * @param prefixLength 前缀显示位数
	 * @param hideLength 中部隐藏位数
	 * @param suffixLength 后缀显示位数
	 * @return java.lang.String
	 */
	public static String desensitize(String value, int prefixLength, int hideLength,
			int suffixLength) {
		if (StringUtils.isEmpty(value)) {
			return value;
		}

		isTrue(value.length() < (prefixLength + hideLength + suffixLength),
				"the prefix, hide and suffix's length is bigger than value's length!");
		String replacement = "$1" + "*".repeat(Math.max(0, hideLength)) + "$2";
		return value.replaceAll("(\\d{" + prefixLength + "})\\d{" + hideLength + "}(\\d{"
				+ suffixLength + "})", replacement);
	}

	/**
	 * 按平均长度进行数据脱敏
	 *
	 * @param value 值
	 * @return java.lang.String
	 */
	public static String desensitize(String value) {
		if (StringUtils.isBlank(value)) {
			return value;
		}
		int hideLength = (int) Math.ceil(value.length() / 3D);
		int prefixLength = (int) Math.floor((value.length() - hideLength) / 2D);
		int suffixLength = value.length() - prefixLength - hideLength;
		return desensitize(value, prefixLength, hideLength, suffixLength);
	}

	private static void isTrue(boolean expression, String message) {
		if (expression) {
			throw new IllegalArgumentException(message);
		}
	}

	/**
	 * 根据指定长度进行数据脱敏
	 *
	 * @param value 值
	 * @param prefixLength 前缀显示位数, -1时表示按均进行数据脱敏
	 * @param suffixLength 后缀显示位数, -1时表示按均进行数据脱敏
	 * @return
	 */
	public static String desensitize(String value, int prefixLength, int suffixLength) {
		if (StringUtils.isEmpty(value)) {
			return value;
		}
		if (prefixLength > value.length() || suffixLength > value.length()
				|| prefixLength + suffixLength > value.length()) {
			return desensitize(value, 0, value.length(), 0);
		}
		int hideLength = (int) Math.ceil(value.length() / 3D);
		prefixLength = prefixLength == -1
				? (int) Math.floor((value.length() - hideLength) / 2D)
				: prefixLength;
		suffixLength = suffixLength == -1 ? (value.length() - prefixLength - hideLength)
				: suffixLength;
		hideLength = value.length() - prefixLength - suffixLength;
		return desensitize(value, prefixLength, hideLength, suffixLength);
	}

	public static void main(String[] args) {
		System.out.println(desensitize("18211111111"));
		System.out.println(desensitize("510522199509264831"));
	}
}
